package org.linlinjava.litemall.admin.job;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.admin.beans.dto.MemberNotifyDto;
import org.linlinjava.litemall.core.notify.AwsNotifyService;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.util.AdminCouponDateUtil;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.Arrays;
import java.util.List;

import com.alibaba.fastjson.JSON;

import static org.linlinjava.litemall.admin.util.AdminResponseCode.MOBILE_CODE_ONE;

/**
 * 支付成员工作
 *
 * @author yliyun
 * @program: litemall
 * @description: 付费会员提醒
 * @author: chenyu
 * @create: 2022-03-23 20:33
 * @date 2022/09/14
 */
@Component
public class PayMemberJob implements Job {
    /**
     * 日志记录器
     */
    private final Log logger = LogFactory.getLog(PayMemberJob.class);

    /**
     * 卢米埃支付会员用户服务
     */
    @Autowired
    private LumierePayMemberUserService lumierePayMemberUserService;

    /**
     * 卢米埃支付会员服务
     */
    @Autowired
    private LumierePayMemberService lumierePayMemberService;

    /**
     * litemall系统配置服务
     */
    @Autowired
    private LitemallSystemConfigService litemallSystemConfigService;

    /**
     * 通知服务
     */
    @Autowired
    private NotifyService notifyService;

    /**
     * 用户服务
     */
    @Autowired
    private LitemallUserService userService;

    /**
     * 卢米埃成员点服务水平
     */
    @Autowired
    private LumiereLevelMemberPointService lumiereLevelMemberPointService;

    /**
     * aws通知服务
     */
    @Autowired
    private AwsNotifyService awsNotifyService;

    /**
     * 注意助手
     */
    @Autowired
    private NoticeHelper noticeHelper;


    @Autowired
    private LumiereCouponUserService lumiereCouponUserService;

    @Autowired
    private LumiereCouponStrategyService lumiereCouponStrategyService;


    /**
     * 付费会员到期提醒（1次，三天前）
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void notifyPayMemberExpire(){
        logger.info("付费会员到期提醒（1次，三天前）");
        List<LumierePayMemberUser> payMemberUsers = lumierePayMemberUserService.list();
        payMemberUsers.stream().forEach(payMemberUser->{
            String payMemberName = lumierePayMemberService.findById(payMemberUser.getPayMemberId()).getName();
            if(Duration.between(LocalDateTime.now(),payMemberUser.getEndTime()).toDays()==3){
               if(ObjectUtil.isNotEmpty(payMemberUser.getUserId())){
                   LitemallUser litemallUser = userService.findById(payMemberUser.getUserId());
                   //发系统通知
                   noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER, "Pay member expiration reminder", "The following membership has expire: "+payMemberName, payMemberUser.getUserId(), null);
                   //发送 短信 或者 邮箱
                   if(StrUtil.isNotEmpty(litemallUser.getEmail())&&RegexUtil.isEmailExact(litemallUser.getEmail())){
                       awsNotifyService.noticeMail("Pay member expiration reminder", "The following membership has expire: "+payMemberName, "The following membership has expire: "+payMemberName,litemallUser.getEmail());
                   }
                   if(StrUtil.isNotEmpty(litemallUser.getMobile())&&RegexUtil.isMobileExact(litemallUser.getMobile())){
                       awsNotifyService.sendSms(MOBILE_CODE_ONE + litemallUser.getMobile(), "The following membership has expire: "+payMemberName,Constants.AWS_MESSAGE_TYPE_PROMOTIONAL);
                   }
               }else if(StrUtil.isNotBlank(payMemberUser.getUserName())){
                   //发送 短信 或者 邮箱
                   if(RegexUtil.isEmailExact(payMemberUser.getUserName())){
                       awsNotifyService.noticeMail("Pay member expiration reminder", "The following membership has expire: "+payMemberName, "The following membership has expire: "+payMemberName,payMemberUser.getUserName());
                   }
                   if(RegexUtil.isMobileExact(payMemberUser.getUserName())){
                       awsNotifyService.sendSms(MOBILE_CODE_ONE + payMemberUser.getUserName(), "The following membership has expire: "+payMemberName,Constants.AWS_MESSAGE_TYPE_PROMOTIONAL);
                   }
               }
            }
        });
    }

    /**
     * 付费会员到期提醒
     */
    @Scheduled(cron = "0 30 0 * * ?")
    public void notifyPayMember() {
        logger.info("系统开启任务付费会员是否需要提醒用户");
        String systemValue = litemallSystemConfigService.queryByKeyName(Constants.SYSTEM_PAY_MEMBER);

        MemberNotifyDto dto = JSON.parseObject(systemValue, MemberNotifyDto.class);

        if (dto.getIsNotify() == 1 && dto.getAdvanceDay() != null) {
            LumierePayMemberUserExample example = new LumierePayMemberUserExample();
            List<LumierePayMemberUser> memberUsers = lumierePayMemberUserService.list(example);
            Integer days = dto.getAdvanceDay();
            memberUsers.forEach(memberUser -> {
                if (memberUser.getEndTime() != null) {
                    LocalDate endDate = memberUser.getEndTime().toLocalDate();
                    Period next = Period.between(LocalDate.now(), endDate);
                    if (next.getDays() == days) {
                        //发起提醒
                        if (memberUser.getUserId() != null) {
                            LitemallUser user = userService.findById(memberUser.getUserId());
                            //发送短信类型
                            Byte[] types = dto.getTypes();

                            if (null != user.getMobile()) {
                                for (int i = 0; i < types.length; i++) {
                                    if (types[i] == 1) {
                                        awsNotifyService.sendSms(MOBILE_CODE_ONE + user.getMobile(), dto.getContent(),Constants.AWS_MESSAGE_TYPE_TRANSACTIONAL);
                                    } else if (types[i] == 0) {
                                        logger.info("进入次数" +i + ": notifyPayMember定时任务进入 -> 付费会员到期提醒（2次，一周前、两天前）");
                                        noticeHelper.noticeUser(Constants.MSG_TYPE_SYSTEM, "付费会员到期提醒", dto.getContent(), user.getId(), null);
//                      noticeHelper.noticeUser(1+user.getMobile(), dto.getContent(), org.linlinjava.litemall.db.beans.Constants.AWS_MESSAGE_TYPE_TRANSACTIONAL);
                                    }
                                }
                            }
                            //邮箱发送邮件
                            if (user.getEmail() != null) {
                                for (int i = 0; i < types.length; i++) {
                                    if (types[i] == 2) {
//                      awsNotifyService.sendSms(1+user.getMobile(), dto.getContent(), org.linlinjava.litemall.db.beans.Constants.AWS_MESSAGE_TYPE_TRANSACTIONAL);
                                        notifyService.notifyMail("会员过期提醒", dto.getContent(), user.getEmail());
                                    }
                                }
                            }
                        }
                    }
                }
            });

        }

    }

    /**
     * 通知级别成员
     */
    @Scheduled(cron = "0 30 1 * * ?")
    public void notifyLevelMember() {
        logger.info("系统开启任务等级会员是否需要提醒用户");
        String systemValue = litemallSystemConfigService.queryByKeyName(Constants.SYSTEM_LEVEL_MEMBER);

        MemberNotifyDto dto = JSON.parseObject(systemValue, MemberNotifyDto.class);
        Integer days = dto.getAdvanceDay();
        if (dto.getIsNotify() == 1 && dto.getAdvanceDay() != null) {
            LumiereLevelMemberPointExample example = new LumiereLevelMemberPointExample();
            example.or();
            List<LumiereLevelMemberPoint> ps = lumiereLevelMemberPointService.list(example);
            ps.stream().forEach(pUser -> {
                if (pUser.getEndTime() != null) {
                    LocalDate endDate = pUser.getEndTime().toLocalDate();
                    Period next = Period.between(LocalDate.now(), endDate);
                    if (next.getDays() == days) {
                        //发起提醒
                        if (pUser.getUserId() != null) {
                            LitemallUser user = userService.findById(pUser.getUserId());
                            //发送短信类型
                            Byte[] types = dto.getTypes();

                            if (user.getMobile() != null) {
                                for (int i = 0; i < types.length; i++) {
                                    if (types[i] == 1) {
                                        awsNotifyService.sendSms(MOBILE_CODE_ONE + user.getMobile(), dto.getContent(), org.linlinjava.litemall.db.beans.Constants.AWS_MESSAGE_TYPE_TRANSACTIONAL);
                                    } else if (types[i] == 0) {
                                        noticeHelper.noticeUser(Constants.MSG_TYPE_SYSTEM, "等级会员到期提醒", dto.getContent(), user.getId(), null);
//                      noticeHelper.noticeUser(1+user.getMobile(), dto.getContent(), org.linlinjava.litemall.db.beans.Constants.AWS_MESSAGE_TYPE_TRANSACTIONAL);
                                    }
                                }
                            }
                            //邮箱发送邮件
                            if (user.getEmail() != null) {
                                for (int i = 0; i < types.length; i++) {
                                    if (types[i] == 2) {
                                        notifyService.notifyMail("会员过期提醒", dto.getContent(), user.getEmail());
                                    }
                                }
                            }
                        }
                    }
                }
            });

        }

    }

    /**
     * 发放优惠券
     */
    //@Scheduled(cron = "0 0 1 * * ?")
    public void distributeCoupon() {
        logger.info("发送付费会员绑定的优惠券");
        //查找付费会员策略策略
        List<LumiereCouponStrategy> couponStrategies = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                .eq(LumiereCouponStrategy::getCouponType, 6)
                .eq(LumiereCouponStrategy::getStatus, 1));
        //查找购买的付费会员
        couponStrategies.stream().forEach(lumiereCouponStrategy -> {
            List<LumierePayMemberUser> lumierePayMemberUsers = lumierePayMemberUserService.listMemberUserByMemberId(Arrays.asList(lumiereCouponStrategy.getPayMember()));
            for (LumierePayMemberUser lumierePayMemberUser : lumierePayMemberUsers) {
                //给所有买了会员的用户根据发放周期发放 优惠券
                switch (lumiereCouponStrategy.getPeriod()){
                    case 1: {
                        LocalDateTime now = LocalDateTime.now(); // 获取当前日期时间
                        grant(lumiereCouponStrategy,lumierePayMemberUser.getUserId(),now.with(LocalTime.MIN),now.with(LocalTime.MAX));
                        break;
                    }
                    case 2: {
                        LocalDateTime startOfWeek = LocalDateTime.now().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).withHour(0).withMinute(0).withSecond(0);
                        LocalDateTime endOfWeek = LocalDateTime.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)).withHour(23).withMinute(59).withSecond(59);
                        grant(lumiereCouponStrategy,lumierePayMemberUser.getUserId(),startOfWeek,endOfWeek);
                        break;
                    }
                    case 3: {
                        // 获取本月起始时间
                        LocalDateTime startOfMonth = LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth())
                                .with(LocalTime.MIN);
                        LocalDateTime endOfMonth = LocalDateTime.now().with(TemporalAdjusters.lastDayOfMonth())
                                .with(LocalTime.MAX);
                        grant(lumiereCouponStrategy,lumierePayMemberUser.getUserId(),startOfMonth,endOfMonth);
                        break;
                    }
                    case 4: {
                        // 获取本年起始时间
                        LocalDateTime startOfYear = LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear())
                                .with(LocalTime.MIN);
                        LocalDateTime endOfYear = LocalDateTime.now().with(TemporalAdjusters.lastDayOfYear())
                                .with(LocalTime.MAX);
                        grant(lumiereCouponStrategy,lumierePayMemberUser.getUserId(),startOfYear,endOfYear);
                        break;
                    }
                }
            }
        });
    }


    private void grant(LumiereCouponStrategy lumiereCouponStrategy, Integer userId, LocalDateTime startTime, LocalDateTime endTime) {
        //判断是否发放过
        long count = lumiereCouponUserService.count(Wrappers.lambdaQuery(LumiereCouponUser.class)
                .eq(LumiereCouponUser::getStrategyId, lumiereCouponStrategy.getId())
                .eq(LumiereCouponUser::getCouponId, lumiereCouponStrategy.getCouponId())
                .eq(LumiereCouponUser::getUserId, userId)
                .between(LumiereCouponUser::getAddTime,startTime,endTime));
        if(count>0){return;}
        for(int i=1;i<=lumiereCouponStrategy.getReleasedQuantity();i++){
            long nextId = IdUtil.getSnowflake(2, 2).nextId();
            LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(lumiereCouponStrategy);
            LitemallUser litemallUser = userService.findById(userId);
            LumiereCouponUser lumiereCouponUser = LumiereCouponUser.builder()
                    .userId(litemallUser.getId())
                    .strategyId(lumiereCouponStrategy.getId())
                    .couponId(lumiereCouponStrategy.getCouponId())
                    .userName(litemallUser.getUsername())
                    .startTime(localDateTimes[0])
                    .endTime(localDateTimes[1])
                    .code(String.valueOf(nextId))
                    .addTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .deleted(false)
                    .build();
            lumiereCouponUserService.save(lumiereCouponUser);
        }
    }

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        this.distributeCoupon();
    }
}
